<link rel="import" href="../../bower_components/paper-material/paper-material.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../../bower_components/paper-styles/typography.html">
<link rel="import" href="../../bower_components/paper-radio-group/paper-radio-group.html">
<link rel="import" href="../../bower_components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="../../bower_components/paper-progress/paper-progress.html">
<link rel="import" href="../helpers/stack-forms-behavior.html">
<link rel="import" href="../app-form/app-form.html">
<script type="text/javascript" src="../machine-create-fields.js" inline></script>
<dom-module id="stack-create">
    <template>
        <style include="shared-styles forms single-page">
            paper-material {
                display: block;
                padding: 24px;
            }

            #content {
                max-width: 900px;
            }

            paper-progress {
                position: absolute;
                bottom: 87px;
                width: 100%;
                left: 0;
                right: 0;
            }

            :host>::slotted(paper-input-container) {
                padding-top: 16px;
                padding-bottom: 16px;
            }

            paper-item.lead {
                font-size: 2em;
            }

            paper-toggle-button[disabled]::slotted() {
                color: rgba(0, 0, 0, 0.32);
            }

            paper-toggle-button::slotted(paper-input-container input) {
                color: color: rgba(0, 0, 0, 0.54);
            }

            .spacer {
                display: block;
                height: 24px;
                width: 100%;
            }

            .bottom-actions {
                padding-left: 20px;
            }

            *:not(paper-button)[disabled] {
                display: none;
            }

            paper-radio-group {
                padding: 16px 8px;
            }

            @media (max-width: 800px) {
                .desc {
                    display: none;
                }
            }

            .desc {
                width: 250px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }

            .single-head {
                @apply --stack-page-head-mixin
            }
        </style>
        <div id="content">
            <paper-material class="single-head layout horizontal">
                <span class="icon">
                    <iron-icon icon="[[section.icon]]"></iron-icon>
                </span>
                <div class="title flex">
                    <h2>
                        Create Stack
                    </h2>
                    <div class="subtitle">
                        from [[template.name]]
                        <a href$="/templates/[[template.id]]">
                            <iron-icon icon="icons:link"></iron-icon>
                        </a>
                        <span class="desc" hidden$="[[!template.description]]">([[template.description]])</span>
                    </div>
                </div>
            </paper-material>
            <paper-material hidden$="[[template.id]]">
                <p>Template is missing</p>
            </paper-material>
            <paper-material hidden$="[[!template.id]]">
                <app-form id="create_stack" fields="{{fields}}" templateid="{{template.id}}" workflow="install" url="/api/v1/stacks" on-request="_handleRequest"
                    on-response="_handleResponse" on-error="_handleError" btncontent="create stack" format-payload></app-form>
            </paper-material>
        </div>
    </template>
    <script>
        Polymer({
            is: 'stack-create',
            behaviors: [
                stackFormsBehavior
            ],
            properties: {
                model: {
                    type: Object
                },
                section: {
                    type: Object
                },
                stack: {
                    type: Object
                },
                form: {
                    type: Object,
                    value: {}
                },
                params: {
                    type: Object
                },
                template: {
                    type: Object,
                    computed: '_fromTemplate(params, model.templates.*)'
                },
                fields: {
                    type: Array,
                    value: [],
                    notify: true
                },
                keys: {
                    type: Array
                },
                clouds: {
                    type: Array
                },
                images: {
                    type: Array
                },
                uri: {
                    type: String
                },
                yaml_inputs: {
                    type: String,
                    notify: true
                }
            },

            observers: [
                '_computeFields(template, template.inputs, template.inputs.*, model.templatesArray.*, model.cloudsArray.*, model.keys.*, params)'
            ],

            listeners: {
                'change': '_updateFields',
                'iron-select': '_updateFields',
                'update-keys': 'updateKeys',
                'format-payload': '_updateFields'
            },
            ready: function () {},
            _fromTemplate: function (params, templates) {
                if (params.template && this.model.templates) {
                    var yaml_inputs = '';
                    this.model.templates[params.template].inputs.forEach(function (inp) {
                        yaml_inputs += inp.name + ': ';
                        var val = inp.value = !undefined ? inp.value : inp.defaultValue || inp.default;
                        if (inp.value == 'custom')
                            val = JSON.stringify(inp.customValue);
                        yaml_inputs += val + '\n';
                    }, this);
                    this.set('yaml_inputs', yaml_inputs);
                    // pass values into form's stackinputs default value
                    var ind;
                    var stackinputsField = this.fields.find(function (f, index) {
                        ind = index;
                        return f.name == "stackinputs";
                    });
                    this.set('fields.' + ind + '.defaultValue', this.yaml_inputs);
                    // console.log('template is redefined');

                    var yaml_or_form = 'form';
                    var template = this.model.templates[params.template];
                    // console.log('Computing Fields started');

                    if (this.fields) {
                        var yf = this.fields.find(function (f) {
                            return f.name == 'yaml_or_form'
                        });
                        if (yf && yf.value)
                            yaml_or_form = yf.value;
                        else
                            yaml_or_form = 'form';
                    }

                    var ret = [{
                        name: "name",
                        label: "Stack Name",
                        type: "text",
                        value: "",
                        isLead: true,
                        defaultValue: "",
                        placeholder: "",
                        errorMessage: "Please enter a name for the stack",
                        show: true,
                        required: true
                    }, {
                        name: "description",
                        label: "Stack Description",
                        type: "textarea",
                        value: "",
                        defaultValue: "",
                        placeholder: "",
                        helptext: "Choose a usefull description for your stack",
                        errorMessage: "Please enter stacks's description",
                        show: true,
                        required: false
                    }, {
                        name: "yaml_or_form",
                        label: "YAML or form",
                        type: "radio",
                        value: yaml_or_form,
                        defaultValue: "form",
                        helptext: "Choose the way you want to insert inputs",
                        errorMessage: "Choose an input format",
                        show: true,
                        required: true,
                        options: [{
                            title: "Form",
                            val: "form"
                        }, {
                            title: "YAML",
                            val: "yaml"
                        }]
                    }, {
                        name: "stackinputs",
                        label: "Stack Inputs YAML",
                        type: "textarea",
                        value: this.yaml_inputs,
                        defaultValue: this.yaml_inputs,
                        placeholder: '',
                        helptext: "Enter the stack inputs in yaml format",
                        errorMessage: "Please enter stacks's inputs",
                        show: true,
                        required: true,
                        showIf: {
                            fieldName: "yaml_or_form",
                            fieldValues: ["yaml"]
                        }
                    }];

                    if (template && template.inputs) {
                        template.inputs.forEach(function (inp) {
                            inp['showIf'] = {
                                fieldName: "yaml_or_form",
                                fieldValues: ["form"]
                            }
                            inp['label'] = inp.name.replace(/_/g, ' ');
                            inp['defaultValue'] = inp.default;
                            inp['value'] = inp['value'] || inp.default;

                            // Temp, before Tosca uses 'required' key
                            inp.required = false;

                            // Uncomment when TOSCA uses 'required' key
                            // if (!inp.required){
                            //     inp.required = false;
                            // }

                            // make key dropdown
                            if (inp.name.startsWith('mist_key')) {
                                inp.type = 'ssh_key';
                                // inp.type = 'dropdown';
                                inp.helptext = 'Select key';
                                inp.options = []; //this.model.keysArray;
                            }

                            // make cloud dropdown
                            if (inp.name.startsWith('mist_cloud')) {
                                inp.label = 'cloud';
                                inp.type = 'mist_dropdown';
                                inp.helptext = 'Select cloud';
                                inp.options = []; //this.model.cloudsArray;

                                inp.options.forEach(function (o) {
                                    o.disabled = !o.enabled;
                                });
                            }

                            // make image dropdown & dependent on cloud
                            if (inp.name.startsWith("mist_image")) {
                                var xid = inp.name.split("mist_image")[1];
                                inp.show = false;
                                inp.type = 'mist_dropdown';
                                inp.helptext = 'Select image';
                                inp.showIf = {
                                    fieldName: "mist_cloud" + xid,
                                    fieldExists: true
                                }
                            }

                            // make network dropdown & dependent on cloud
                            if (inp.name.startsWith("mist_networks")) {
                                var xid = inp.name.split("mist_networks")[1];
                                inp.show = false;
                                inp.type = 'mist_dropdown';
                                inp.helptext = 'Select network';
                                inp.showIf = {
                                    fieldName: "mist_cloud" + xid,
                                    fieldExists: true
                                }
                            }

                            // make image & location dependent on cloud
                            if (inp.name.startsWith("mist_location")) {
                                var xid = inp.name.split("mist_location")[1];
                                inp.show = false;
                                inp.type = 'mist_dropdown';
                                inp.helptext = 'Select location';
                                inp.showIf = {
                                    fieldName: "mist_cloud" + xid,
                                    fieldExists: true
                                }
                            }

                            // make size dependent on cloud
                            if (inp.name.startsWith("mist_size")) {
                                var xid = inp.name.split("mist_size")[1];
                                inp.show = false;
                                inp.type = 'mist_size';
                                inp.helptext = 'Machine size';
                                inp.showIf = {
                                    fieldName: "mist_cloud" + xid,
                                    fieldExists: true
                                }
                            }

                            // prepare mist tags
                            if (inp.name.startsWith("mist_tags")) {
                                inp.show = false;
                                inp.type = 'mist_tags';
                                inp.helptext = inp.description;
                                inp.value = [];
                            }

                            // prepare mist machine
                            if (inp.name.startsWith("mist_machine")) {
                                inp.label = inp.name.split("mist_machine_")[1] || "";
                                inp.required = true;
                                if (inp.name.endsWith("list")) {
                                    inp.multi = true;
                                } else {
                                    inp.multi = false;
                                }
                                inp.quantity = 1;
                                inp.valid = false;
                                inp.show = true;
                                inp.type = 'mist_machine';
                                inp.cloud = '';
                                inp.machine = '';
                                inp.image = '';
                                inp.size = '';
                                inp.location = '';
                                inp.key = '';
                                inp.networks = [];
                                inp.value = {};
                                inp.helptext = inp.description;
                                if (this.model){
                                    inp.clouds = this.model.clouds;
                                    inp.keys = this.model.keys;
                                }
                            }

                            // hide mist api credential inputs
                            if (["mist_token", "script_path", "mist_uri", "mist_username", "mist_password"].indexOf(inp.name) > -1) {
                                inp.hidden = true;
                                inp.show = false;
                                inp.required = false;
                            }

                            ret.push(inp);
                        }, this);
                    }

                    ret.push({
                        name: "deploy",
                        label: "Deploy Now",
                        type: "toggle",
                        value: true,
                        defaultValue: true,
                        placeholder: true,
                        helptext: "Enable this option to deploy your stack now",
                        errorMessage: "",
                        show: true,
                        required: false
                    });
                    this.set('fields', ret);

                    return this.model.templates[params.template];
                } else {
                    return {
                        name: "Template is missing"
                    }
                    console.log('template is missing');
                }
            },

            _computeFields: function (template, templateInps, templateInputs, modelTemplates, clouds, keys,
                params) {
                this.fields.forEach(function (inp, index) {
                    if (inp.name.startsWith('mist_key')) {
                        this.set('fields.' + index + '.options', this.model.keysArray);
                    }

                    if (inp.name.startsWith('mist_cloud')) {
                        this.set('fields.' + index + '.options', this.model.cloudsArray);
                        this.fields[index].options.forEach(function (o) {
                            o.disabled = !o.enabled;
                        })
                    }

                    if (inp.name.startsWith('mist_tags')) {
                        this.set('fields.' + index + '.value', []);
                    }

                    if (inp.name.startsWith('mist_')) {
                        this.set('fields.' + index + '.label', this.get('fields.' + index + '.label').replace('mist ', ''));
                    }

                    if (inp.options && inp.options.length == 1) {
                        if (inp.type == "dropdown")
                            this.set('fields.' + index + '.value', inp.options[0].val);
                        else
                            this.set('fields.' + index + '.value', inp.options[0].id);
                    }

                    if (inp.name.startsWith("mist_machine")) {
                        inp.keys = this.model.keys;
                    }
                }, this);

            },

            _updateFields: function (event) {
                // if a cloud changed
                if (this.fields && event && event.path.map(function(i){return i.id;}).join(',').indexOf("mist_cloud") > -1) {
                    var fieldName = event.path.find(function(f){
                            return f.id && f.id.indexOf('mist_cloud') > -1
                        }),
                        fieldIndex = fieldName && this.fieldIndexByName(fieldName.id.replace('app-form-create_stack-','')),
                        field = fieldIndex > -1 && this.fields[fieldIndex];

                    if (field && field.name.startsWith('mist_cloud') && this.model.clouds[field.value]) {
                        function copy(o) { // deep copy an array of objects
                            var output, v, key;
                            output = Array.isArray(o) ? [] : {};
                            for (key in o) {
                                v = o[key];
                                output[key] = (typeof v === "object") ? copy(v) : v;
                            }
                            return output;
                        }
                        // reset fields if cloud changed
                        var fields = copy(this.fields);
                        this.set('fields', []);
                        this.set('fields', fields);
                    }
                }
                var e = Polymer.dom(event);
                var changeInYaml = e && e.path && e.path.indexOf(document.querySelector("paper-textarea#app-form-create_stack-stackinputs")) > -1;
                if (changeInYaml) {
                    var yaml = document.querySelector("paper-textarea#app-form-create_stack-stackinputs").value;
                    var yaml_array = yaml.split('\n');
                    var inputs = [];
                    yaml_array.forEach(function (line) {
                        var name = line.split(':')[0].trim();
                        var value = line.split(':')[1];
                        if (value)
                            value = value.trim();
                        inputs[name] = value;
                    });

                    this.fields.forEach(function (f, index) {
                        if (inputs[f.name])
                            this.set('fields.' + index + '.value', inputs[f.name])
                    }, this)
                } else {
                    var cloud = this.fields.find(function (f) {
                        return f.name.startsWith("mist_cloud");
                    });
                    var yaml_inputs = '';
                    this.fields.forEach(function (inp, index) {
                        var fieldCloud, // cloud field Object
                            xid, // resource batch index type string ex _1
                            cloudId; // mist cloud id

                        if (['name', 'description', 'yaml_or_form', 'stackinputs', 'deploy'].indexOf(
                                inp.name) == -1) {
                            yaml_inputs += inp.name + ': ';
                            var preformatedValue = inp.preformatPayloadValue ? inp.preformatPayloadValue.apply(inp.value) : inp.value;
                            var val = preformatedValue ? JSON.stringify(preformatedValue) : inp.defaultValue;
                            if (inp.value == 'custom') {
                                val = JSON.stringify(inp.customValue);
                            }
                            yaml_inputs += val + '\n';
                        }

                        // mist-machine contains its own cloud value
                        if (inp.name.startsWith("mist_machine")) {
                            if (this.model) {
                                inp.clouds = this.model.clouds;
                                inp.keys = this.model.keys;
                            }
                        }
                        if (cloud && cloud.value) {
                            if (inp.name.startsWith("mist_cloud")) {
                                xid = inp.name.split("mist_cloud")[0];
                                cloudId = inp.value;
                                if (cloudId && this.fieldIndexByName('mist_size' + xid) > -1) {
                                    if (["onapp", "vsphere", "libvirt", "gce"].indexOf(this.model.clouds[
                                            cloudId].provider) > -1) {
                                        this.set('fields.' + this.fieldIndexByName('mist_size' +
                                            xid) + '.custom', true);
                                        this.set('fields.' + this.fieldIndexByName('mist_size' +
                                            xid) + '.customValue', {});
                                    } else {
                                        this.set('fields.' + this.fieldIndexByName('mist_size' +
                                            xid) + '.custom', false);
                                        this.set('fields.' + this.fieldIndexByName('mist_size' +
                                            xid) + '.customValue', false);
                                    }
                                }
                                if (!inp.show) {
                                    inp.excludeFromPayload = true;
                                } else {
                                    inp.excludeFromPayload = false;
                                }
                            }
                            if (inp.name.startsWith("mist_location")) {
                                xid = inp.name.split("mist_location")[0];
                                fieldCloud = this.fields.find(function (f) {
                                    return f.name.startsWith("mist_cloud" + xid);
                                }) || cloud;
                                cloudId = fieldCloud.value;
                                if (cloudId)
                                    inp['options'] = Object.values(this.model.clouds[cloudId].locations);
                            }
                            if (inp.name.startsWith("mist_image")) {
                                xid = inp.name.split("mist_image")[0];
                                fieldCloud = this.fields.find(function (f) {
                                    return f.name.startsWith("mist_cloud" + xid);
                                }) || cloud;
                                cloudId = fieldCloud.value;
                                if (this.model && cloudId)
                                    inp['options'] = this.model.clouds[cloudId].imagesArray;
                            }
                            if (inp.name.startsWith("mist_networks")) {
                                xid = inp.name.split("mist_networks")[0];
                                fieldCloud = this.fields.find(function (f) {
                                    return f.name.startsWith("mist_cloud" + xid);
                                }) || cloud;
                                cloudId = fieldCloud.value;
                                if (this.model && cloudId)
                                    inp['options'] = Object.values(this.model.clouds[cloudId].networks) || [];
                                else
                                    inp['options'] = [];
                            }
                            if (inp.name.startsWith("mist_size")) {
                                xid = inp.name.split("mist_size")[0];
                                fieldCloud = this.fields.find(function (f) {
                                    return f.name.startsWith("mist_cloud" + xid);
                                }) || cloud;
                                cloudId = fieldCloud.value;
                                if (cloudId) {
                                    inp['options'] = this.model.clouds[cloudId].sizesArray ? this.model.clouds[cloudId].sizesArray : [];
                                    if (["onapp", "vsphere", "libvirt"].indexOf(this.model.clouds[cloudId].provider) > -1) {
                                        var provider = this.model.clouds[cloudId].provider,
                                            fields = MACHINE_CREATE_FIELDS.find(function(p) {return p.provider == provider}).fields;
                                        inp['custom'] = true;
                                        inp["value"] = "custom";
                                        inp["customSizeFields"] = fields.find(function(f){return f.type == "mist_size"}).customSizeFields;
                                    }
                                    else
                                        inp['custom'] = false;
                                }
                            }

                            if (inp.options && inp.options.length == 1) {
                                if (inp.type == "dropdown") {
                                    this.set('fields.' + index + '.value', f.options[0]
                                        .val);
                                }
                                else {
                                    this.set('fields.' + index + '.value', f.options[0]
                                        .id);
                                }
                            }
                        }
                    }.bind(this));

                    this.set('yaml_inputs', yaml_inputs);

                    // pass values into form's stackinputs value
                    var ind;
                    var stackinputsField = this.fields.find(function (f, index) {
                        ind = index;
                        return f.name == "stackinputs";
                    });

                    this.set('fields.' + ind + '.value', this.yaml_inputs);
                }
            },

            fieldIndexByName: function (name) {
                var index = this.fields.findIndex(function (f) {
                    return f.name == name;
                });
                return index;
            },

            updateKeys: function (e) {
                // console.log('_updateKeys', e);
                this.async(function () {
                    // console.log(this.template);
                    if (this.fields)
                        this.fields.forEach(function (f, index) {
                            // make key dropdown && select newly created key
                            if (f.name.startsWith('mist_key')) {
                                f.options = this.model.keysArray;
                                this.set('fields.' + index + '.value', e.detail.key);
                            }
                        }, this);
                }.bind(this), 1000);
            },

            _handleRequest: function (e) {

            },

            _handleResponse: function (e) {
                // console.log('create stack ', e);
                var response = YAML.parse(e.detail.xhr.response);
                var sid = response.id;
                this.dispatchEvent(new CustomEvent('go-to', { bubbles: true, composed: true, detail: {
                    url: '/stacks/' + sid
                } }));

                this.debounce('resetForm', function () {
                    this._resetForm();
                }, 500);
            },

            _handleError: function (e) {

            },

            _resetForm: function (e) {
                // Reset form
                for (var attr in this.form) {
                    this.set('form.' + attr, '');
                }
                // Reset Form Fields
                this.fields.forEach(function (el, index) {
                    if (el.showIf) {
                        this.set('fields.' + index + '.show', false);
                    }
                    // Reset Form Fields Validation
                    this._resetField(el, index);
                }, this);
            },
            _computeProviderLogo: function (provider) {
                return 'assets/providers/provider-' + provider + '.png';
            },
            _resetField: function (el, index) {
                // this.set('fields.' + index + '.value', el.defaultValue);
                // var input = this.shadowRoot.querySelector('#' + el.name);
                // if (input) {
                //     input.invalid = false;
                // }
            }
        });
    </script>
</dom-module>